package cn1shared.ui;


import com.codename1.ui.Button;
import com.codename1.ui.Command;
import com.codename1.ui.Display;
import com.codename1.ui.Image;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


/**
 * Button that the user can press and hold for a second action.
 */
public class PressHoldButton extends Button {

	private static final Timer TIMER = new Timer();

	private TimerTask task;
	private boolean hack = false;
	private List<ActionListener> holdListeners = new ArrayList<ActionListener>();

	public PressHoldButton(String text) {
		super(text);
	}

	public PressHoldButton(Command cmd) {
		super(cmd);
	}

	public PressHoldButton(Image icon) {
		super(icon);
	}

	public PressHoldButton(String text, Image icon) {
		super(text, icon);
	}

	public void addActionListener(final ActionListener listener) {
		// wrap listeners with hack
		ActionListener wrapper = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				evt.consume();
				if (hack) {
					hack = false;
					return;
				}
				listener.actionPerformed(evt);
			}
		};
		super.addActionListener(wrapper);
	}

	public void addHoldListener(ActionListener listener) {
		holdListeners.add(listener);
	}

	private void fireHoldListeners() {
		ActionEvent e = new ActionEvent(this);
		for (ActionListener l : holdListeners) {
			l.actionPerformed(e);
		}
	}

	@Override
	public void pointerPressed(final int x, final int y) {
		cancelTask();
		task = new TimerTask() {
			@Override
			public void run() {
				boolean isPressed = getStyle() == getPressedStyle();
				if (!isPressed)
					return;
				Display.getInstance().vibrate(100);
				fireHoldListeners();
				/*
					Hack for very stupid issue with the button state, which I cannot set manually.
					The only way to bring the button state back to default is by calling pointerReleased(x,y)
					but this fires the action event (we don't want that when the user is holding the button)
				 */
				hack = true;
				pointerReleased(x, y);
			}
		};
		TIMER.schedule(task, 1000, 1000);
		super.pointerPressed(x, y);
	}

	@Override
	public void pointerReleased(int x, int y) {
		cancelTask();
		super.pointerReleased(x, y);
	}

	private void cancelTask() {
		if (task != null) {
			task.cancel();
			task = null;
		}
	}


}
